<template>
  <div>
      <el-radio-group v-model="radio" style="margin: 20px 0;display: flex;justify-content: center;">
        <el-radio :label="1">事件</el-radio>
        <el-radio :label="2">显隐</el-radio>
      </el-radio-group>
      <div v-show="radio==1">
        <el-form ref="ruleForm" :rules="rules" :model="form" class="eventForm" label-width="100px">
            <el-form-item label="源组件" prop="source">
              <el-select v-model="form.source" size="small" clearable placeholder="请选择" @change="sourceSelect">
                <el-option
                  v-for="item in options"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="源事件" prop="sourceEvent">
              <el-select v-model="form.sourceEvent" size="small" clearable placeholder="请选择">
                <el-option
                  v-for="item in sourceEventOption"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="目标组件" prop="target">
              <el-select v-model="form.target" size="small" clearable placeholder="请选择" @change="targetSelect">
                <el-option
                  v-for="item in options"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="目标事件" prop="targetEvent">
              <el-select v-model="form.targetEvent" size="small" clearable placeholder="请选择">
                <el-option
                  v-for="item in targetEventOption"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="触发时">
                <el-radio-group v-model="form.trigger">
                  <el-radio :label="1">after</el-radio>
                  <el-radio :label="2">before</el-radio>
                </el-radio-group>
            </el-form-item>
            <el-form-item>
              <el-button size="small" @click="reset">重置</el-button>
              <el-button type="primary" size="small" @click="save">保存</el-button>
            </el-form-item>
          </el-form>
          <el-table
            :data="tableData"
            @row-click="rowClick"
            style="width: 100%">
            <el-table-column
              prop="source"
              label="源组件"
            >
            </el-table-column>
            <el-table-column
              prop="sourceEvent"
              label="源事件"
            >
            </el-table-column>
            <el-table-column
              prop="target"
              label="目标组件">
            </el-table-column>
            <el-table-column
              prop="targetEvent"
              label="目标事件">
            </el-table-column>
            <el-table-column label="操作">
              <template slot-scope="scope">
                <el-button
                  size="mini"
                  type="danger"
                  @click.stop="handleDelete(scope.$index, scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
      </div>
      <div v-show="radio==2">

          <el-form class="shForm" ref="shForm" :rules="sfRules" :model="shForm" label-width="100px">
            <el-form-item label="源组件" prop="sourceValue">
              <el-select v-model="shForm.sourceValue" size="small" clearable placeholder="请选择" @change="SourceChange">
                <el-option
                  v-for="item in options"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="字典" prop="dicValue">
              <el-select v-model="shForm.dicValue" size="small" clearable placeholder="请选择">
                <el-option
                  v-for="item in dicData"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="目标组件" prop="targetValue">
              <el-select v-model="shForm.targetValue" multiple collapse-tags size="small" clearable placeholder="请选择">
                <el-option
                  v-for="item in targetOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </el-form-item>
            <el-form-item>
              <el-button size="small" @click="cenlReset">重置</el-button>
              <el-button type="primary" size="small" @click="keep">保存</el-button>
            </el-form-item>
          </el-form>
          <el-table
            highlight-current-row
            @row-click="shRowClick"
            :data="shTableData"
            style="width: 100%">
                <el-table-column
                  prop="sourceValue"
                  label="源组件">
                </el-table-column>
                <el-table-column
                  prop="dicValue"
                  label="字典">
                </el-table-column>
                <el-table-column
                  prop="targetValue"
                  label="目标组件">
                </el-table-column>
                <el-table-column label="操作">
                  <template slot-scope="scope">
                    <el-button
                      size="mini"
                      type="danger"
                      @click.stop="shDelete(scope.$index, scope.row)">删除</el-button>
                  </template>
                </el-table-column>
          </el-table>
      </div>
      <el-collapse v-model="collapse" accordion>
          <el-collapse-item name="1" title="事件属性">
              <el-collapse v-model="eventCollapse" accordion>
                  <el-collapse-item :name="index" :title="item.label" v-for="(item, index) in eventContent" :key="'event_'+item.label+'_'+index">
                      <p>{{item.label}}事件响应函数</p>
                      <monaco-editor v-model="item.value"
                                     height="200"
                                     :keyIndex="'event-'+item.label"
                                     :options="monacoOptions"></monaco-editor>
                      <p>{{item.label}}响应可视化内容</p>
                      <div class="eventDiv">
                          <span class="eventSpan">打开方式：</span>
                          <el-select v-model="item.openMode" size="mini" filterable clearable style="width: 200px;">
                              <el-option v-for="(item, index) in openMode" :label="item.label" :value="item.value" :key="'openMode_'+index"></el-option>
                          </el-select>
                      </div>
                      <div class="eventDiv" v-if="item.openMode == 'commonDialog' || item.openMode == 'commonMiniDialog'">
                          <span class="eventSpan">弹框名称：</span>
                          <el-input v-model="item.dialogName" size="mini" clearable class="eventWidth"></el-input>
                      </div>
                      <div class="eventDiv" v-if="item.openMode != 'void'">
                          <span class="eventSpan">内容：</span>
                          <el-select v-model="item.openContent" size="mini" filterable clearable style="width: 200px;">
                              <el-option v-for="(item, index) in openContent" :label="item.label" :value="item.value" :key="'openContent_'+index"></el-option>
                          </el-select>
                      </div>
                      <div class="eventDiv" v-if="item.openContent == 'url'">
                          <span class="eventSpan">URL地址：</span>
                          <el-input v-model="item.url" size="mini" clearable class="eventWidth"></el-input>
                      </div>
                      <div class="eventDiv" v-if="item.openContent == 'designScheme'">
                          <span class="eventSpan">设计方案：</span>
                          <el-select v-model="item.designScheme" size="mini" filterable clearable style="width: 200px;">
                              <el-option v-for="(item, index) in designScheme" :label="item.label" :value="item.value" :key="'openContent_'+index"></el-option>
                          </el-select>
                      </div>
                  </el-collapse-item>
              </el-collapse>
          </el-collapse-item>
      </el-collapse>
  </div>
</template>
<script>
import MonacoEditor from '@utils/monaco-editor'
import baseComp from "./baseComp";
export default {
    name: 'event',
    components: {MonacoEditor},
    extends: baseComp,
  props:{
      data: {
          type:Object,
          default:()=>{}
      },
      //配置表单数据集
      widgetForm: {
          type:Object,
          default:()=>{}
      },
      //事件串联配置表格数据
    tableData:{
      type:Array,
      default:()=>[]
    },
      //显隐控制配置表格数据
    shTableData:{
      type:Array,
      default:()=>[]
    }
  },
  data(){
    return{
      dicData:[],
      radio:1,
      form:{  //事件串联表单
        source:'',
        target:'',
        sourceEvent:'',
        targetEvent:'',
        trigger:1
      },
      shForm:{  //显隐控制表单
        sourceValue:'',
        dicValue:'',
        targetValue:[]
      },
      targetOptions:[],
      options: [],  //导入的组件数量集合
      sourceEventOption:[], //源目标组件所有事件名数据集合
      targetEventOption:[],
      rules: {
        source: [
          { required: true, message: '请选择', trigger: 'change' }
        ],
        target: [
          { required: true, message: '请选择', trigger: 'change' }
        ],
        sourceEvent: [
          { required: true, message: '请选择', trigger: 'change' }
        ],
        targetEvent: [
          { required: true, message: '请选择', trigger: 'change' }
        ],
      },
      sfRules: {
        sourceValue: [
          { required: true, message: '请选择', trigger: 'change' }
        ],
        dicValue:[
          { required: true, message: '请选择', trigger: 'change' }
        ],
        targetValue:[
          { required: true, message: '请选择', trigger: 'change' }
        ]

      },
        collapse: [],
        eventCollapse: [],
        monacoOptions: {
            fullScreen: true,
            minimap: {
                enabled: false,
            },
        },
        //事件串联函数钩子数据存储对象
        eventRelationObj: {
            CustomEvents: {},
            CustomDropDisplay: {}
        },
        //自定义事件编辑数据集
        eventContent: [],
        designScheme: [
            {label: '三层子规则', value: 'set_564044352846962688_713467384668758016_614760953019506688_714417605527650304_1685082821506'},
            {label: '三层高级子规则', value: 'set_564044352846962688_713467384668758016_614760953019506688_714417605527650304_1685085640945'},
        ]
    }
  },
  watch:{
      widgetForm:{
          handler(val) {
              this.reset();
              this.init(val);
          },
          deep:true,
          immediate: true
      },
      //当前配置项数据
      'data.prop': {
          handler(val) {
              this.eventContent = [];
              let event = this.data.event;
              let eventConfig = this.data.eventConfig;
              for (let eventName in event) {
                  let func = event[eventName];
                  let funcStr = "{}"
                  if (typeof func == 'function'){
                      funcStr = func.toString();
                  }else {
                      funcStr = func;
                  }
                  let config = {};
                  if (eventConfig){
                      config = eventConfig[eventName];
                  }
                  let eventObj = {
                      label: eventName,
                      value: funcStr,
                      ...config
                  };
                  this.eventContent.push(eventObj)
              }
          },
          deep:true,
          immediate: true
      },
      eventContent: {
          handler(newVal, oldVal) {
              for (let newValKey in newVal) {
                  let event = newVal[newValKey];
                  this.$set(this.data.event, event.label, event.value);
                  if (!this.data.eventConfig){
                      this.data.eventConfig = {};
                  }
                  this.$set(this.data.eventConfig, event.label, {
                      openMode: event.openMode,
                      dialogName: event.dialogName,
                      openContent: event.openContent,
                      url: event.url,
                      designScheme: event.designScheme
                  })
              }
          },
          deep:true,
          immediate: true
      }
  },
  mounted(){
      this.getDesignScheme();
  },

    methods:{
      /**
       * 组装设计器引入表单数据集
       * @param val
       */
    init(val){
      this.options=[];
      val.column.forEach(el => {
        // 本身
        this.options.push({
          value:el.prop,
          label:el.label
        })
        if(el.type=="group" && el.children.column.length>0) {
          el.children.column.forEach(item => {
            this.options.push({
              value: item.prop,
              label: item.label
            })
          })
        }
      });
    },
      /**
       * 事件串联源组件选择变化事件
       * @param val
       */
    sourceSelect(val){
      this.form.source=val;
      this.form.sourceEvent="";
      this.sourceEventOption=[];
      this.selectCompHandle(this.sourceEventOption, val,this.widgetForm.column)
      if(this.widgetForm.group){
        this.widgetForm.group.forEach(every=>{
          this.selectCompHandle(this.sourceEventOption, val,every.column)
        })
      }
    },
      /**
       * 目标组件选择
       * @param val
       */
    targetSelect(val){
      this.form.target=val;
      this.form.targetEvent="";
      this.targetEventOption=[];
      this.selectCompHandle(this.targetEventOption, val,this.widgetForm.column)
      if(this.widgetForm.group){
        this.widgetForm.group.forEach(every=>{
          this.selectCompHandle(this.targetEventOption, val,every.column)
        })
      }
    },
      /**
       * 封装当前选择组件所有事件数据集合
       * @param eventOption
       * @param val
       * @param array
       */
      selectCompHandle(eventOption, val,array){
          array.forEach(item=>{
              if(val==item.prop){
                  if('click' in item){
                      eventOption.push({
                          value:'click',
                          label:'click'
                      })
                  }
                  if('change' in item){
                      eventOption.push({
                          value:'change',
                          label:'change'
                      })
                  }
                  if('blur' in item){
                      eventOption.push({
                          value:'blur',
                          label:'blur'
                      })
                  }
                  if('focus' in item){
                      eventOption.push({
                          value:'focus',
                          label:'focus'
                      })
                  }
                  if('event' in item){
                      for(let key in item.event){
                          eventOption.push({
                              value:key,
                              label:key
                          })
                      }
                  }
              }
          })
      },
      /**
       * 重置事件串联表单数据
       */
    reset(){
      for(let key in this.form){
        this.form[key]='';
      }
      this.form.trigger=1;
    },
      /**
       * 事件串联配置数据保存
       */
    save(){
      this.$refs.ruleForm.validate((valid) => {
          if (valid) {
              //判断事件串联form表单是否有ID值，如果有则更新事件串联表格数据集，没有则新增
            if(this.form.id){
              this.tableData.forEach(item=>{
                if(item.id==this.form.id){
                  for(let key in this.form){
                    this.$set(item, key,this.form[key]);
                  }
                  //清空事件表单ID属性。
                  delete this.form['id']
                }
              })
              // this.$emit('EventTableData', this.tableData,this.form,'edit');
              this.reset();
            }else{
              this.tableData.push({
                id:parseInt(new Date().getTime()/1000),
                source:this.form.source,
                target:this.form.target,
                sourceEvent:this.form.sourceEvent,
                targetEvent:this.form.targetEvent,
                trigger:this.form.trigger
              })
              // this.$emit('EventTableData', this.tableData,this.form,'add');
              this.reset();
            }
              this.widgetForm.eventRelationTable = this.tableData;
              this.eventTableData();
          } else {
            return false;
          }
        });
    },
        /**
         * 事件串联配置数据删除操作
         * @param i
         * @param r
         */
        handleDelete(i,r){
            this.tableData.splice(i,1)
            delete this.form['id']
            // this.$emit('EventTableData', this.tableData,r,'del');
            this.widgetForm.eventRelationTable = this.tableData;
            this.eventTableData();
        },
        /**
         * 事件串联配置数据表格行点击事件
         * @param row
         */
        rowClick(row){
            this.form=JSON.parse(JSON.stringify(row));
        },
        /**
         * 封装事件配置数据对象。
         */
        eventTableData(){
            //重置事件串联
            this.eventRelationObj.CustomEvents = {};
            for (let i = 0; i < this.tableData.length; i++) {
                let row = this.tableData[i];
                if (!this.eventRelationObj.CustomEvents[row.source]) {
                    this.eventRelationObj.CustomEvents[row.source] = {};
                }
                let eventObject = '';
                let builtInKey = '';
                //判断内置事件
                if (this.isBuiltInEvent(row.sourceEvent)){
                    builtInKey = "builtIn";
                    eventObject = this.createEventRelation(row, false);
                }
                //自定义事件
                else {
                    builtInKey = "custom";
                    eventObject = this.createEventRelation(row, true);
                }
                if (!this.eventRelationObj.CustomEvents[row.source][builtInKey]) {
                    this.eventRelationObj.CustomEvents[row.source][builtInKey] = {};
                }
                if (!this.eventRelationObj.CustomEvents[row.source][builtInKey][row.sourceEvent]) {
                    this.eventRelationObj.CustomEvents[row.source][builtInKey][row.sourceEvent] = [];
                }
                let array = this.eventRelationObj.CustomEvents[row.source][builtInKey][row.sourceEvent];
                if (!array.includes(eventObject)){
                    array.push(eventObject);
                }
            }
            //赋值事件传递，并重写目标源事件内容
            this.setEventRelationObjToColumn();
        },
        /**
         * 设置目标源事件函数内容
         */
        setEventRelationObjToColumn(){
            let that = this;
            //设置值
            function setValue(column, relationKey, key) {
                if (!column){
                    return;
                }
                for (let builtInKey in that.eventRelationObj[relationKey][key]) {
                    let customEvents = that.eventRelationObj[relationKey][key][builtInKey];
                    for (let customEventsKey in customEvents) {
                        let customEventStr = customEvents[customEventsKey].join(";") + ";";
                        //将需要更改的函数去掉最后的“}”，并拼接需要添加的函数快。
                        let func = column[customEventsKey];
                        if(!func){
                            func = "({value,column}) => {}"
                        }
                        if (typeof func == 'function'){
                            func = func.toString();
                        }
                        let lastIndex = func.lastIndexOf('}');
                        func = func.substring(0, lastIndex);
                        //去掉历史事件控制函数快 this.CustomEvents, this.CustomDropDisplay
                        func = func.replace(/this\.CustomEvents[\s\S]*?;/gi, '');
                        func = func.replaceAll(/this\.CustomDropDisplay[\s\S]*?;/gi, '');
                        //判断是内置还是自定义事件
                        if (builtInKey == 'builtIn'){
                            that.$set(column,customEventsKey,eval(func + ";" + customEventStr + "}"));
                        }else {
                            that.$set(column.event,customEventsKey,eval(func + ";" + customEventStr + "}"));
                        }
                    }
                }
            }
            for (let relationKey in this.eventRelationObj){
                for (let key in this.eventRelationObj[relationKey]) {
                    for (let i = 0; i < this.widgetForm.column.length; i++) {
                        let column = this.widgetForm.column[i];
                        if (column.type == 'group'){
                            let column_ = column.children.column.find(item => item.prop == key);
                            setValue(column_, relationKey, key);
                            break;
                        }else {
                            if (column.prop == key){
                                setValue(column, relationKey, key);
                                break;
                            }
                        }
                    }
                }
            }
        },
        /**
         * 判断指定函数是否为内置函数
         */
        isBuiltInEvent(event){
            let inEvents = ["change", "click", "focus", "blur"];
            return inEvents.includes(event);
        },

        /**
         * 创建事件串联事件钩子函数字符串
         */
        createEventRelation(row, custom){
            let customEventStr = '';
            if (!custom){
                customEventStr = 'this.CustomEvents("' +row.target +'","' +row.targetEvent +'")';
            }else {
                customEventStr = 'this.CustomEvents("' +row.target +'","' +row.targetEvent +'",data)';
            }
            return customEventStr;
        },
      /**
       * 显隐控制源目标组件选择change事件
       * @param val
       * @constructor
       */
    SourceChange(val){
      this.shForm.sourceValue=val;
      this.shForm.dicValue="";
      this.dicData=[];
      this.widgetForm.column.forEach(el=>{
        if(el.type=="group"){
          el.children.column.forEach(key=>{
            if(val==key.prop && key.dicData){
              this.dicData=key.dicData;
            }else if(val==key.prop && key.dicUrl){
              let that=this;
              var httpRequest = new XMLHttpRequest();// new对象
                  httpRequest.open(key.dicMethod, key.dicUrl, true);// get表示请求方式、url请求的地址
                  httpRequest.send();// 发送请求
                  httpRequest.onreadystatechange = function () {//返回处理
                      if (httpRequest.readyState == 4 && httpRequest.status == 200) {
                          var res = JSON.parse(httpRequest.responseText); // 返回数据转换成json数据
                      //     // 可对数据进行操作...
                          that.dicData=res.data;
                      }
                  }
            }

          })
        }
        if(val==el.prop && el.dicData){
          this.dicData=el.dicData;
        }else if(val==el.prop && el.dicUrl){
          let that=this;
          var httpRequest = new XMLHttpRequest();// new对象
              httpRequest.open(el.dicMethod, el.dicUrl, true);// get表示请求方式、url请求的地址
              httpRequest.send();// 发送请求
              httpRequest.onreadystatechange = function () {//返回处理
                  if (httpRequest.readyState == 4 && httpRequest.status == 200) {
                      var res = JSON.parse(httpRequest.responseText); // 返回数据转换成json数据
                  //     // 可对数据进行操作...
                      that.dicData=res.data;
                  }
              }
        }
      })
          //目标组件，排除了源组件的所有组件即为目标组件
      this.targetOptions=this.options.filter(item=>{return item.value!=val});
    },
      /**
       * 显隐控制配置保存
       */
    keep(){
      this.$refs.shForm.validate((valid) => {
        if (valid) {
          if(this.shForm.id){//修改
              this.shTableData.forEach(item=>{
                if(item.id==this.shForm.id){
                  for(let key in this.shForm){
                    this.$set(item, key,this.shForm[key]);
                  }
                  delete this.shForm['id']
                }
              })
              // this.$emit('shTable', this.shTableData,this.shForm.sourceValue,'edit');
              this.cenlReset();
            }else{//新增
              this.shTableData.push({
                id:parseInt(new Date().getTime()/1000),
                sourceValue:this.shForm.sourceValue,
                dicValue:this.shForm.dicValue,
                targetValue:this.shForm.targetValue
              })
              // this.$emit('shTable', this.shTableData,this.shForm.sourceValue,'add');
              this.cenlReset();
            }
            this.widgetForm.shTableData = this.shTableData;
            this.createShTableData();
          } else {
            return false;
          }
        });
    },
      /**
       * 重置显隐控制配置表单数据
       */
    cenlReset(){
      for(let key in this.shForm){
        if(key=='targetValue'){
          this.shForm[key]=[];
        }else{
          this.shForm[key]='';
        }
      }
    },
      /**
       * 显隐控制配置数据删除操作
       * @param i
       * @param r
       */
    shDelete(i,r){
      this.shTableData.splice(i,1)
          this.widgetForm.shTableData = this.shTableData;
          this.createShTableData();
      // this.$emit('shTable', this.shTableData,r.sourceValue,'del');
    },
      /**
       * 显隐控制配置数据表单行点击事件
       * @param row
       */
    shRowClick(row){
      this.SourceChange(row.sourceValue)
      this.$nextTick(()=>{
        this.shForm=JSON.parse(JSON.stringify(row));
      });
    },
        /**
         *
         * 创建显隐控制数据集事件集
         */
        createShTableData(){
            //重置显隐控制
            this.eventRelationObj.CustomDropDisplay = {};
            for (let i = 0; i < this.shTableData.length; i++) {
                let row = this.shTableData[i];
                if (!this.eventRelationObj.CustomDropDisplay[row.sourceValue]) {
                    this.eventRelationObj.CustomDropDisplay[row.sourceValue] = {};
                }
                let eventObject = "this.CustomDropDisplay(value,column)";
                let builtInKey = 'builtIn';
                if (!this.eventRelationObj.CustomDropDisplay[row.sourceValue][builtInKey]) {
                    this.eventRelationObj.CustomDropDisplay[row.sourceValue][builtInKey] = {};
                }
                if (!this.eventRelationObj.CustomDropDisplay[row.sourceValue][builtInKey]['change']) {
                    this.eventRelationObj.CustomDropDisplay[row.sourceValue][builtInKey]['change'] = [];
                }
                let array = this.eventRelationObj.CustomDropDisplay[row.sourceValue][builtInKey]['change'];
                if (!array.includes(eventObject)){
                    array.push(eventObject);
                }
            }
            //赋值事件传递，并重写目标源事件内容
            this.setEventRelationObjToColumn();
        },
        /**
         * 获取设计方案
         */
        getDesignScheme(){
            this.$myAxios.get('/deployApi/operation/getOperation').then(res => {
                if (res.data.code == 0){
                    this.designScheme = res.data.data.map(item => {
                        return {
                            label: item.name,
                            value: item.processKey
                        }
                    });
                }else {
                    this.designScheme = [];
                }
            })
        }
  }
}
</script>
<style lang="less" scoped>
::v-deep{
  .eventForm,.shForm{
    .el-select,.el-input__inner{
      width:220px;
    }
  }
}
.eventDiv{
    padding: 5px 0px 5px 0px;
    .eventWidth{
        width: 200px;
    }
    .eventSpan{
        display: inline-block;
        width: 80px;
        text-align: left;
    }
}
</style>
